package function

import (
	"fmt"
	"strings"
)

func intSum(x, y int) int {
	return x + y
}

func sayHello() {
	fmt.Println("hello world")
}

func intSum2(a ...int) int {
	sum := 0
	for _, v := range a {
		sum += v
	}
	return sum
}

func intSum3(x int, y ...int) int {
	sum := x
	for _, v := range y {
		sum = sum + v
	}
	return sum
}

func calc(x, y int) (int, int) {
	return x + y, x - y
}

func calc2(x, y int) (sum, sub int) {
	sum = x + y
	sub = x - y
	return
}

func testLocalVar2(x, y int) {
	fmt.Println(x, y) //函数的参数也是只在本函数中生效
	if x > 0 {
		z := 100 //变量z只在if语句块生效
		fmt.Println(z)
	}
	//fmt.Println(z)//此处无法使用变量z
}

func testLocalVar3() {
	for i := 0; i < 10; i++ {
		fmt.Println(i) //变量i只在当前for语句块中生效
	}
	//fmt.Println(i) //此处无法使用变量i
}

type calcFunc func(int, int) int

func add(x, y int) int {
	return x + y
}

func sub(x, y int) int {
	return x - y
}

func print(s []int, f calcFunc) []int {
	s1 := make([]int, len(s))

	for i := 0; i < len(s); i++ {
		v := f(s[i], s[i])
		s1[i] = v
	}

	return s1
}

func adder() func(int) int {
	var x int
	return func(y int) int {
		x = x + y
		return x
	}
}

func adder2(x int) func(int) int {
	return func(y int) int {
		x = x + y
		return x
	}
}

func addSuffix(suffix string) func(string) string {
	return func(s string) string {
		if strings.HasSuffix(s, suffix) {
			return s
		} else {
			return s + "." + suffix
		}
	}
}

func calc3(base int) (func(int) int, func(int) int) {
	add := func(i int) int {
		base += i
		return base
	}

	sub := func(i int) int {
		base -= i
		return base
	}
	return add, sub
}

func ff() int {
	x := 5
	defer func() int {
		x++
		return x
	}()
	return x
}

func ff2() (x int) {
	x = 5
	defer func() int {
		x++
		return x
	}()

	return 10
}

func ff3() (y int) {
	x := 5
	defer func() int {
		x += 1
		return x
	}()
	return x
}

func ff4() (x int) {
	defer func(x int) {
		x++
	}(x)
	return 5
}

func TestFun1() {
	a := intSum(2, 3)
	fmt.Println(a)

	sayHello()

	ret1 := intSum2()           //0
	ret2 := intSum2(10)         //10
	ret3 := intSum2(10, 20)     //30
	ret4 := intSum2(10, 20, 30) //60
	fmt.Println(ret1, ret2, ret3, ret4)

	ret5 := intSum3(100)             //100
	ret6 := intSum3(100, 10)         //110
	ret7 := intSum3(100, 10, 20)     //130
	ret8 := intSum3(100, 10, 20, 30) //160
	fmt.Println(ret5, ret6, ret7, ret8)

	fmt.Println(calc(2, 3))  //5, -1
	fmt.Println(calc2(2, 3)) //5,-1

	var f calcFunc
	f = add
	fmt.Println(f(2, 3)) //5
	f = sub
	fmt.Println(f(2, 3)) //-1

	s := []int{1, 2, 3, 4, 5}
	fmt.Println(print(s, add)) //[2 4 6 8 10]
	fmt.Println(print(s, sub)) //[0 0 0 0 0]

	a1 := func(x, y int) int {
		return x + y
	}

	fmt.Println(a1(2, 3)) //5

	f1 := adder()
	fmt.Println(f1(10)) //10
	fmt.Println(f1(20)) //30
	fmt.Println(f1(30)) //60

	f2 := adder()
	fmt.Println(f2(40)) //40
	fmt.Println(f2(50)) //90

	var f3 = adder2(10)
	fmt.Println(f3(10)) //20
	fmt.Println(f3(20)) //40
	fmt.Println(f3(30)) //70

	jpgSuffix := addSuffix("jpg")
	fmt.Println(jpgSuffix("aa")) //aa.jpg

	f11, f12 := calc3(10)
	fmt.Println(f11(1), f12(2)) //11 9
	fmt.Println(f11(3), f12(4)) //12 8
	fmt.Println(f11(5), f12(6)) //13 7

	fmt.Println(ff())  //5
	fmt.Println(ff2()) //11
	fmt.Println(ff3()) //5
	fmt.Println(ff4()) //5
}

func funcA() {
	fmt.Println("func A")
}

func funcB(catch bool) {
	if catch {
		defer func() {
			err := recover()
			if err != nil {
				fmt.Println("recover in B")
			}
		}()
	}

	funcD()
}

func funcC() {
	fmt.Println("func C")
}

func funcD() {
	fmt.Println("func D")
	funcE()
}

func funcE() {
	fmt.Println("func E")
	panic("panic E")
}

func TestFunc2() {
	defer func() {
		err := recover()
		if err != nil {
			fmt.Println("recover")
		}
	}()

	funcA()
	funcB(true)
	funcC()
}
